﻿using STHPMS1.Common.C_Entity;
using STHPMS1.Common.C_Entity.Stmpms1;
using STHPMS1.ICore;
using STHPMS1.ICore.I_Core;
using STHPMS1.ICore.I_UI;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using STHPMS1.Common.C_Extension;
using STHPMS1.Web.W_Model;
using System.Collections.Generic;
using Newtonsoft.Json;
using STHPMS1.Common.C_Utils;
using System.Data;
using System.Reflection;
using System.Linq.Expressions;


namespace STHPMS1.Web.W_Controller.Decision.Needs
{
    [RoutePrefix("api/DnTrafficWay")]
    public class DnTrafficWayController : STHPMS1.Web.W_Core.MyController
    {
        [Route("")]
        [Route("page/{page?}", Name = "GetDnTrafficWayByPage")]
        [Route("rows/{rows?}")]
        [Route("page/{page?}/rows/{rows?}")]
        public IHttpActionResult Get(string rdid = null, int page = 1, int rows = 10)
        {
            int p = page;
            int s = rows;

            PagingInfo info = new PagingInfo();
            info.PageIndex = p > 0 ? p - 1 : 0;
            info.PageSize = s;
            info.TotalRecords = 0;
            //条件
            Expression<Func<Dn_Traffic_Way, bool>> exp = null;

            exp = pre => pre.Segid.Contains(rdid);

            var data = this.Scene.Bll.Dn_Traffic_Way.Get<Dn_Traffic_Way>(exp, info).ToArray();
            if (data == null) return NotFound();

            var result = new { rows = data, total = info.TotalRecords };

            return Ok(result);
        }

        [Route("")]
        public void Delete(Dn_Traffic_Way entity)
        {
            this.Scene.Bll.Dn_Traffic_Way.Remove(entity);//删除养护路段和关联单元
        }

        /// <summary>
        /// 计算剩余寿命
        /// </summary>
        /// <param name="rdid">路线编号</param>
        /// <param name="zzl">增长率</param>
        /// <returns></returns>
        [Route("calculate")]
        public HttpResponseMessage PostCalculate(string rdid, string zzl)
        {
            try
            {
                //轴型轮组类型（车辆类型1006或1007）
                List<string> safttypes = new List<string>();
                safttypes.Add("1s+1d+2d");
                safttypes.Add("1s+1d+3d");
                safttypes.Add("1s+2d+3d");
                safttypes.Add("2s+1d+3d");
                safttypes.Add("1s+2d+1d+1d");
     

                //TODO:Dm_Trafaxleparam
                //查询路线的技术等级
                //int roadClass = this.Scene.Bll.B_Roadway.GetRoadRdClass(rdid);
                //根据路线编号，查询路段
                List<B_Invntory> b_Invntorys = this.Scene.Bll.B_Invntory.GetList<B_Invntory>(rdid);
                if (b_Invntorys.Count == 0)
                {
                    var res = new HttpResponseMessage(HttpStatusCode.InternalServerError)
                    {
                        Content = new StringContent("当前路线下没有已知路段"),
                        ReasonPhrase = "Server Error"
                    };
                    throw new HttpResponseException(res);
                }

                //查询DM_DEFAULT_TRAFFIC表
                IEnumerable<Dm_Default_Traffic> dm_trafaxleparam = this.Scene.Bll.Dm_Default_Traffic.Get<Dm_Default_Traffic>(null,null);

                //一个路段对应一个系数表
                Dictionary<string, DataTable> dic_Invntory_Trafaxle = new Dictionary<string, DataTable>();
                Dictionary<string, double> b_zzsj = new Dictionary<string, double>();//保存路段编号和轴载设计当量
                foreach (B_Invntory b in b_Invntorys)
                {
                    //查询该路段的历年的交通量导入年份分组
                    List<string> years = this.Scene.Bll.Dn_Traffic_Way.GetYear(b);
                    if (years.Count == 0)
                    {
                        continue; //该路段没有交通量
                    }

                    //查看该路段是否有初次通车年份的轴载设计当量
                    #region 计算初次通车年份的轴载设计当量
                    //查询该路段是否已经有了初次通车年份的轴载设计当量
                    double _load = this.Scene.Bll.Dn_Traffic_Way.Exists(b.Segid);
                    if (_load == 0) //不存在该轴载当量
                    {
                        //查询该路段的初次通车年份的交通量(路线编号,通车年份)
                        DataTable dtTrafaxleparamYear = this.Scene.Bll.S_Apply.GetApply(b);
                        if (dtTrafaxleparamYear == null || dtTrafaxleparamYear.Rows.Count == 0)
                        {
                            continue; //该路段没有初次通车年份的交通量
                            //throw new Exception("该线路路段没有初次通车年份的交通量数据，无法计算设计轴载当量,起点和结束桩号:" + b.Beginmp + "--" + b.Endmp + ",初次通车时间:" + b.Begindate.ToString());
                        }

                        #region 路段和弯沉刚性系数表
                        //构建路段的系数dataTable
                        DataTable dtXS = new DataTable();
                        dtXS.Columns.Add(new DataColumn("轴型轮组类型"));
                        dtXS.Columns.Add(new DataColumn("前轴"));//dtXS.Columns.Add(new DataColumn("前c1"));
                         dtXS.Columns.Add(new DataColumn("中前轴"));//dtXS.Columns.Add(new DataColumn("前c2"));
                        dtXS.Columns.Add(new DataColumn("中后轴"));//dtXS.Columns.Add(new DataColumn("后c1"));
                         dtXS.Columns.Add(new DataColumn("后轴"));//dtXS.Columns.Add(new DataColumn("后c2"));
                         dtXS.Columns.Add(new DataColumn("前轴轮组"));
                        dtXS.Columns.Add(new DataColumn("中前轴轮组"));
                         dtXS.Columns.Add(new DataColumn("中后轴轮组"));
                        dtXS.Columns.Add(new DataColumn("后轴轮组"));
                        dtXS.Columns.Add(new DataColumn("车辆数"));

                        //构建刚性系数表
                        DataTable dtGX = new DataTable();
                        dtGX.Columns.Add(new DataColumn("弯沉设计"));
                        dtGX.Columns.Add(new DataColumn("一天当量轴次"));
                        //AADT数据
                        double aadt = 0;
                        foreach (Dm_Default_Traffic t in dm_trafaxleparam)
                        {
                            DataRow r = dtXS.NewRow();
                            r["轴型轮组类型"] = t.Shafttype;

                            r["前轴"] = 1 + 1.2 * (t.Front_Axes - 1); //前轴轴数
                            if(safttypes.Contains(t.Shafttype))
                            {
                                r["中前轴"] = 1+1.2*(t.C_Front_Axes-1);//中前轴轴数
                            }
                            if(t.Shafttype=="1s+2d+1d+1d")
                            {
                                r["中后轴"] = 1+1.2*(t.C_Rrear_Axes-1);//中后轴轴数
                            }
                            r["后轴"] = 1+1.2*(t.Rear_Axes-1);//后轴
                            r["前轴轮组"]=6.4;//前轴轮组
                             if(safttypes.Contains(t.Shafttype))
                            {
                                r["中前轴轮组"] = 1;//中前轴轮组
                            }
                             if(t.Shafttype=="1s+2d+1d+1d")
                            {
                                r["中后轴轮组"] = 1;//中后轴轮组
                            }
                             if(t.Shafttype=="1s+1s")
                            {
                                r["后轴轮组"] = 6.4;//后轴轮组
                            }
                             else
                             {
                                  r["后轴轮组"] = 1;//后轴轮组
                             }
               
                            //根据车辆类型和路段，查询初次通车年份的交通量车辆数
                            r["车辆数"] = GetCarCount(dtTrafaxleparamYear, b, t.Carmame);
                            dtXS.Rows.Add(r);

                            //计算刚性弯沉表
                            DataRow g = dtGX.NewRow();
//弯沉设计=前轴*前轴轮组*(t.Front_Axle/100)^4.35 + 中前轴*中前轴轮组*(t.C_Front_Axle/100)^4.35  + 中后轴*中后轴轮组*(t.C_Rrear_Axle/100)^4.35 + 后轴*后轴轮组*(t.Rear_Axle/100)^4.35

                            g["弯沉设计"] = Convert.ToDouble(r["前轴"]) *Convert.ToDouble(r["前轴轮组"]) * Math.Pow(Convert.ToDouble(t.Front_Axle)/100, 4.35) +
                                Convert.ToDouble(r["中前轴"]) *Convert.ToDouble(r["中前轴轮组"]) * Math.Pow(Convert.ToDouble(t.C_Front_Axle)/100, 4.35)+
                                Convert.ToDouble(r["中后轴"]) *Convert.ToDouble(r["中后轴轮组"]) * Math.Pow(Convert.ToDouble(t.C_Rrear_Axle)/100, 4.35)+
                                 Convert.ToDouble(r["后轴"]) *Convert.ToDouble(r["后轴轮组"]) * Math.Pow(Convert.ToDouble(t.Rear_Axle)/100, 4.35);
                            g["一天当量轴次"] = Math.Round(Convert.ToDouble(g["弯沉设计"]) * Convert.ToInt32(r["车辆数"]), 4);
                            dtGX.Rows.Add(g);
                            aadt += Convert.ToDouble(g["一天当量轴次"]);
                        }
                        #endregion

                        #region 车道系数和使用年限计算设计轴载当量
                        //车道系数
                        double cdxs = 0;
                        if (b.Numlanes == null || b.Numlanes == 4)
                        {
                            cdxs = 0.45;
                        }
                        else if (b.Numlanes == 1)
                        {
                            cdxs = 1;
                        }
                        else if (b.Numlanes == 2)
                        {
                            cdxs = 0.65;
                        }
                        else if (b.Numlanes == 6)
                        {
                            cdxs = 0.35;
                        }
                        else if (b.Numlanes == 8)
                        {
                            cdxs = 0.3;
                        }
                        //使用年限
                        double year = 1;
                        if (b.Rdclass_Dictid <= Common.C_Enum.RoadClassEnum.R161.GetEnumValue())
                            year = 15;//一级或告诉公路
                        else if (b.Rdclass_Dictid == Common.C_Enum.RoadClassEnum.R162.GetEnumValue())
                            year = 12;//二级公路
                        else if (b.Rdclass_Dictid == Common.C_Enum.RoadClassEnum.R163.GetEnumValue())
                            year = 8;//三级公路
                        else if (b.Rdclass_Dictid == Common.C_Enum.RoadClassEnum.R164.GetEnumValue())
                            year = 6;//三级公路
                        if (year == 1)
                        {
                            throw new Exception("该路段缺少技术等级,无法推算使用年限,起终桩号为:" + b.Beginmp + "--" + b.Endmp);
                        }
                        //设计年限内当量轴载
                        double sjnx = Math.Round((Math.Pow((1.0 + int.Parse(zzl) / 100.0), year) - 1) * 365 * aadt * cdxs / (int.Parse(zzl) / 100.0));

                        //保存编号和轴载当量
                        b_zzsj.Add(b.Segid, sjnx);
                        #endregion

                    }
                    else
                    {
                        //保存编号和轴载当量
                        b_zzsj.Add(b.Segid, _load);
                    }
                    #endregion


                    #region 计算所有年份的累计轴载当量
                    //所有AADT数据
                    double aadtSum = 0;
                    foreach (string year in years)
                    {
                        b.Begindate = DateTime.Parse(year+"-01-01");//调整通车年份,以便计算每年的交通量
                        //每年的交通量
                        DataTable dtTrafaxleparamYear = this.Scene.Bll.S_Apply.GetApply(b);
                        #region 路段和弯沉刚性系数表
                        //构建路段的系数dataTable
                        DataTable dtXS = new DataTable();
                        dtXS.Columns.Add(new DataColumn("轴型轮组类型"));
                        dtXS.Columns.Add(new DataColumn("前轴"));//dtXS.Columns.Add(new DataColumn("前c1"));
                         dtXS.Columns.Add(new DataColumn("中前轴"));//dtXS.Columns.Add(new DataColumn("前c2"));
                        dtXS.Columns.Add(new DataColumn("中后轴"));//dtXS.Columns.Add(new DataColumn("后c1"));
                         dtXS.Columns.Add(new DataColumn("后轴"));//dtXS.Columns.Add(new DataColumn("后c2"));
                         dtXS.Columns.Add(new DataColumn("前轴轮组"));
                        dtXS.Columns.Add(new DataColumn("中前轴轮组"));
                         dtXS.Columns.Add(new DataColumn("中后轴轮组"));
                        dtXS.Columns.Add(new DataColumn("后轴轮组"));
                        dtXS.Columns.Add(new DataColumn("车辆数"));

                        //构建刚性系数表
                        DataTable dtGX = new DataTable();
                        dtGX.Columns.Add(new DataColumn("弯沉设计"));
                        dtGX.Columns.Add(new DataColumn("一天当量轴次"));
                        //遍历车辆轴重
                        foreach (Dm_Default_Traffic t in dm_trafaxleparam)
                        {
                            DataRow r = dtXS.NewRow();
                             r["轴型轮组类型"] = t.Shafttype;

                            r["前轴"] = 1 + 1.2 * (t.Front_Axes - 1); //前轴轴数
                            if(safttypes.Contains(t.Shafttype))
                            {
                                r["中前轴"] = 1+1.2*(t.C_Front_Axes-1);//中前轴轴数
                            }
                            if(t.Shafttype=="1s+2d+1d+1d")
                            {
                                r["中后轴"] = 1+1.2*(t.C_Rrear_Axes-1);//中后轴轴数
                            }
                            r["后轴"] = 1+1.2*(t.Rear_Axes-1);//后轴
                            r["前轴轮组"]=6.4;//前轴轮组
                             if(safttypes.Contains(t.Shafttype))
                            {
                                r["中前轴轮组"] = 1;//中前轴轮组
                            }
                             if(t.Shafttype=="1s+2d+1d+1d")
                            {
                                r["中后轴轮组"] = 1;//中后轴轮组
                            }
                             if(t.Shafttype=="1s+1s")
                            {
                                r["后轴轮组"] = 6.4;//后轴轮组
                            }
                             else
                             {
                                  r["后轴轮组"] = 1;//后轴轮组
                             }
                            //根据车辆类型和路段，查询初次通车年份的交通量车辆数
                            r["车辆数"] = GetCarCount(dtTrafaxleparamYear, b, t.Carmame);
                            dtXS.Rows.Add(r);

                            //计算刚性弯沉表
                            DataRow g = dtGX.NewRow();
                            //弯沉设计=前轴*前轴轮组*(t.Front_Axle/100)^4.35 + 中前轴*中前轴轮组*(t.C_Front_Axle/100)^4.35  + 中后轴*中后轴轮组*(t.C_Rrear_Axle/100)^4.35 + 后轴*后轴轮组*(t.Rear_Axle/100)^4.35

                            g["弯沉设计"] = Convert.ToDouble(r["前轴"]) *Convert.ToDouble(r["前轴轮组"]) * Math.Pow(Convert.ToDouble(t.Front_Axle)/100, 4.35) +
                                Convert.ToDouble(r["中前轴"]) *Convert.ToDouble(r["中前轴轮组"]) * Math.Pow(Convert.ToDouble(t.C_Front_Axle)/100, 4.35)+
                                Convert.ToDouble(r["中后轴"]) *Convert.ToDouble(r["中后轴轮组"]) * Math.Pow(Convert.ToDouble(t.C_Rrear_Axle)/100, 4.35)+
                                 Convert.ToDouble(r["后轴"]) *Convert.ToDouble(r["后轴轮组"]) * Math.Pow(Convert.ToDouble(t.Rear_Axle)/100, 4.35);
                            g["一天当量轴次"] = Math.Round(Convert.ToDouble(g["弯沉设计"]) * Convert.ToInt32(r["车辆数"]), 4);
                            dtGX.Rows.Add(g);
                            aadtSum += Convert.ToDouble(g["一天当量轴次"]);
                        }
                        #endregion
                    }
                    #endregion

                    //使用年限
                    double yearNew = 1;
                    if (b.Rdclass_Dictid <= Common.C_Enum.RoadClassEnum.R161.GetEnumValue())
                        yearNew = 15;//一级或告诉公路
                    else if (b.Rdclass_Dictid == Common.C_Enum.RoadClassEnum.R162.GetEnumValue())
                        yearNew = 12;//二级公路
                    else if (b.Rdclass_Dictid == Common.C_Enum.RoadClassEnum.R163.GetEnumValue())
                        yearNew = 8;//三级公路
                    else if (b.Rdclass_Dictid == Common.C_Enum.RoadClassEnum.R164.GetEnumValue())
                        yearNew = 6;//三级公路

                    //计算剩余寿命
                    double temp = aadtSum * 365 / b_zzsj[b.Segid];  //年平均日交通量*365/设计年限轴载当量
                    temp = 1 - temp;
                    double rltemp = temp * yearNew;
                    double rl = Math.Round(rltemp, 1); //剩余寿命

                    //存入交通量轴载法表
                    Dn_Traffic_Way t_w = new Dn_Traffic_Way()
                    {
                        Segid = b.Segid,
                        Accuequ_Load = b_zzsj[b.Segid], //设计轴载当量
                        Easl = Math.Round(aadtSum * 365, 2),  //通车至今的轴载当量
                        Svydata = DateTime.Now,

                        Rl = rl  //剩余寿命
                    };

                    //修改已有还是插入新的
                    if (_load == 0)
                    {
                        this.Scene.Bll.Dn_Traffic_Way.Save(t_w);
                    }
                    else
                    {
                        this.Scene.Bll.Dn_Traffic_Way.Update(t_w);
                    }
                }
            }
            catch (Exception ex)
            {
                var res = new HttpResponseMessage(HttpStatusCode.InternalServerError)
                {
                    Content = new StringContent(ex.Message),
                    ReasonPhrase = "Server Error"
                };
                throw new HttpResponseException(res);
            }

            var response = Request.CreateResponse(HttpStatusCode.Created);
            // Generate a link to the new book and set the Location header in the response.
            string uri = Url.Link("GetDnTrafficWayByPage", new { page = 1 });
            response.Headers.Location = new Uri(uri);

            return response;
        }

        /// <summary>
        /// 货车类型查找Dm_Trafaxleparam
        /// </summary>
        /// <param name="lst"></param>
        /// <param name="Cartype">货车类型</param>
        /// <returns></returns>
        //private Dm_Trafaxleparam GetDm_TrafaxleparamByCartype(List<Dm_Trafaxleparam> lst, int Cartype)
        //{
        //    foreach (Dm_Trafaxleparam d in lst)
        //    {
        //        if (d.Cartype == Cartype)
        //        {
        //            return d;
        //        }
        //    }
        //    return null;
        //}

        /// <summary>
        /// 根据汽车类型和路段，返回该类型的交通量数据
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="carType"></param>
        /// <returns></returns>
        private int GetCarCount(DataTable dt, B_Invntory b, string carName)
        {
            foreach (DataRow r in dt.Rows)
            {
                //方向和起始桩号符合要求

                if (carName == "2轴4轮客货车")
                    return (Convert.ToInt32(r["TRUCK_S"]) + Convert.ToInt32(r["CAR_S"]))/2;//小型
                else if (carName == "2轴6轮货车")
                    return Convert.ToInt32(r["TRUCK_M"]);//中型
                else if (carName == "3轴整体式货车")
                    return Convert.ToInt32(r["TRUCK_L"]);//大型
                else if (carName=="4轴及以上整体式货车" || carName== "双前轴整体式货车")
                    return Convert.ToInt32(r["TRUCK_O"]);//特大型
               
                else if (carName=="2轴6轮客车")
                    return Convert.ToInt32(r["CAR_L"]);//大客
                else if (carName == "全挂货车")
                    return Convert.ToInt32(r["ARTVEH"]);//拖挂
                else if(carName=="4轴及以下半挂货车" || carName=="5轴半挂货车" || carName=="6轴及以上半挂货车")               
                    return Convert.ToInt32(r["CONTCAR"]);//集装
                else if (carName=="双前轴半挂式货车")
                    return Convert.ToInt32(r["TRACTOR"]);//拖拉机
            }
            return 0;
        }
    }
}